#pragma once
#include<pthread.h>
#include<iostream> 
#include<unistd.h> 
#include<vector> 
#include<string> 
#include<queue> 
using std::cout;
using std::endl;
struct ThreadInfo{
   pthread_t tid;
   std::string name;
};

template<class T>
class ThreadPool
{
    static const int num = 5;
public:
    ThreadPool(int n = num)
    :_threads(n)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
    }
    bool IsQueueEmpty()
    {
        return task.empty() ;
    }
    std::string GetThreadName(pthread_t tid)
    {
        for(const auto& t:_threads)
        {
            if(t.tid == tid) {
                return t.name;
            }
        }
        return "error";
    }
    //静态成员函数没有this指针
    static void* HandlerTask(void* args)
    {
        ThreadPool<T>* tp = static_cast<ThreadPool<T>*>(args);
        std::string name = tp->GetThreadName(pthread_self());

        while(true)
        {
            tp->Lock();
            while(tp->IsQueueEmpty())
            {
                tp->ThreadSleep();
            }
            T t = tp->pop();
            tp->Unlock();

            cout << name << "处理任务" << endl;
        }
    }
    T pop()
    {
        T t = task.front();
        task.pop();
        return t;
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
    void Start()
    {
        int num = _threads.size();

        for(int i = 0;i < num;++i)
        {
            _threads[i].name = "thread-" + std::to_string(i + 1);
            pthread_create(&(_threads[i].tid),nullptr,HandlerTask,this);
        }
    }
    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }

    void Push(const T& t)
    {
        Lock();
        task.push(t);
        WakeUp();
        Unlock();
    }
    void Lock()
    {
        pthread_mutex_lock(&_mutex);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&_mutex);
    }
private: 
    std::vector<ThreadInfo> _threads;
    std::queue<T> task;

    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

};